﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using Microsoft.Win32;
using System.Net.NetworkInformation;

namespace DeviceManager
{
    public partial class Form1 : Form
    {
        VideoDumpper m_VideoDumpper;
        static System.Threading.Semaphore m_Semaphore;// = new System.Threading.Semaphore();
        MyConfigueManager m_MyConfigueManager;
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            m_MyConfigueManager = new MyConfigueManager();
        }

        class SSDPRequest
        {

            static byte[] data = new XSSDP.ssdp(XSSDP.MessageType.SearchRequest).GetCommandBytes();
            IPAddress m_Ip;
            public SSDPRequest(byte[] ip)
            {
                m_Ip = new IPAddress(ip);
                //Console.WriteLine(m_Ip);
            }
            public String Ip
            {
                get
                {
                    return m_Ip.ToString();
                }
            }
            public void SendSSDPRequest(Object threadContext)
            {
                UdpClient client = new UdpClient();
                client.Send(data, data.Length, m_Ip.ToString(), XSSDP.ssdp.SDDP_PORT);
                lock (data)
                {
                    m_Semaphore.Release();
                }
            }
        }

        string m_start = ""; int m_length = 0;
        string m_ip;
        private void btnSearch_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            foreach (NetworkInterface f in NetworkInterface.GetAllNetworkInterfaces())
            {

                if (f.OperationalStatus == OperationalStatus.Up)
                {
                    foreach (UnicastIPAddressInformation d in f.GetIPProperties().UnicastAddresses)
                    {
                        if (d.Address != null && d.IPv4Mask != null)
                        {
                            m_ip = d.Address.ToString();
                            GetNetWork(d.Address.ToString(), d.IPv4Mask.ToString(), ref m_start, ref m_length);
                        }
                    }
                }
            }
            if (m_start == "")
            {
                labStatus.Text = "not connected to network";
                return;
            }
            labStatus.Text = "start scan network";
            new System.Threading.Thread(new System.Threading.ThreadStart(doSearch)).Start();
        }

        private void doSearch()
        {
            int ip = BitConverter.ToInt32(IPAddress.Parse(m_start).GetAddressBytes(), 0);
            ip = (IPAddress.HostToNetworkOrder(ip));
            m_Semaphore = new System.Threading.Semaphore(0, m_length - 1);
            for (int i = 0; i < m_length - 1; i++)
            {
                ip++;
                byte[] add = BitConverter.GetBytes(ip);
                byte b = add[0]; add[0] = add[3]; add[3] = b; b = add[1]; add[1] = add[2]; add[2] = b;
                SSDPRequest request = new SSDPRequest(add);
                if (request.Ip != m_ip)
                {
                    System.Threading.ThreadPool.QueueUserWorkItem(request.SendSSDPRequest);
                }
            }
            m_Semaphore.WaitOne(60 * 1000);
            labStatus.Text = "scan accomplished";
        }

        AutoReconnectTCPClient m_Client;
        System.Timers.Timer m_Timer;
        bool m_Connected = false;
        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (m_Connected)
            {
                Stop();
            }
            m_Client = new AutoReconnectTCPClient(textBox1.Text, 8000);
            m_Client.DataRecv += new DataRecvDelegate(m_Client_DataRecv);
            if (m_Client.Connect())
            {
                labStatus.Text = "connect to " + textBox1.Text + " ok";
                m_Connected = true;
                m_Timer = new System.Timers.Timer();
                m_Timer.Interval = 1000;
                m_Timer.Elapsed += new System.Timers.ElapsedEventHandler(m_Timer_Elapsed);
                m_Timer.Enabled = true;
            }
            else
            {
                labStatus.Text = "connect to " + textBox1.Text + " failed";
            }
            total = 0;

        }
        private void Stop()
        {
            if (m_Client != null)
            {
                try
                {
                    m_Client.Disconnect();
                    m_Client = null;
                }
                catch (Exception xe)
                {
                }
            }
            if (m_Timer != null)
            {
                m_Timer.Enabled = false;
                m_Timer.Dispose();
                m_Timer = null;
            }
            m_Connected = false;

        }
        void m_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            labStatus.Text = "total data recved from remote : " + total + " speed : " + (total - total_old) + " B/s";
            total_old = total;

        }

        int total = 0;
        int total_old = 0;
        void m_Client_DataRecv(byte[] data)
        {
            total += data.Length;
            m_VideoDumpper.PushData(data, data.Length);
        }


        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            Stop();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            m_MyConfigueManager.AddControl(this.textBox1);
            m_MyConfigueManager.Load();
            //start ssdp response listener
            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(StartListen));
            thread.Start();

            m_VideoDumpper = new VideoDumpper();
            m_VideoDumpper.Init();
        }

        Socket m_Socket = null;
        public void StartListen()
        {
            try
            {
                m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, XSSDP.ssdp.SDDP_PORT);
                EndPoint ep = (EndPoint)iep;
                m_Socket.Bind(iep);
                m_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(XSSDP.ssdp.SDDP_ADDRESS)));
                byte[] buffer = new byte[1024];

                while (true)
                {
                    int len = m_Socket.ReceiveFrom(buffer, ref ep);
                    string ip = ((IPEndPoint)ep).Address.ToString();
                    System.Console.WriteLine("ssdp response = " + ip);
                    string cmd = System.Text.Encoding.Default.GetString(buffer);
                    XSSDP.ssdp obj = XSSDP.ssdp.Parse(buffer, len);
                    if (obj != null && obj.MessageType == XSSDP.MessageType.SearchResponse)
                    {
                        AddDevice(obj);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.ToString());
            }
        }

        public void StopListen()
        {
            if (m_Socket != null)
                m_Socket.Close();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            StopListen();
        }

        private void AddDevice(XSSDP.ssdp device)
        {
            string[] paras = device.Location.Split(new char[] { '?' });
            RemoteService obj = new RemoteService();
            try
            {
                obj.Ip = paras[0];
                obj.m_paras = paras[1];
                obj.ParsePara();
                obj.ProductVersion = device.ProductVersion;
                listBox1.Items.Add(obj);
            }
            catch (Exception ex)
            {
            }
        }

        public void FindNetPara()
        {
            RegistryKey start = Registry.LocalMachine;
            RegistryKey cardServiceName, networkKey;
            string networkcardKey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
            string serviceKey = "SYSTEM\\CurrentControlSet\\Services\\";
            string networkcardKeyName, deviceName;
            string deviceServiceName, serviceName;
            RegistryKey serviceNames = start.OpenSubKey(networkcardKey);
            if (serviceNames == null)
            {
                Console.WriteLine("Bad registry key");
                return;
            }

            string[] networkCards = serviceNames.GetSubKeyNames();

            serviceNames.Close();

            foreach (string keyName in networkCards)
            {

                networkcardKeyName = networkcardKey + "\\" + keyName;

                cardServiceName = start.OpenSubKey(networkcardKeyName);

                if (cardServiceName == null)
                {

                    Console.WriteLine("Bad registry key: {0}", networkcardKeyName);

                    return;

                }

                deviceServiceName = (string)cardServiceName.GetValue("ServiceName");

                deviceName = (string)cardServiceName.GetValue("Description");

                Console.WriteLine("\nNetwork card: {0}", deviceName);

                serviceName = serviceKey + deviceServiceName + "\\Parameters\\Tcpip";

                networkKey = start.OpenSubKey(serviceName);

                if (networkKey == null)
                {

                    Console.WriteLine(" No IP configuration set");

                }

                else
                {

                    string[] ipaddresses = (string[])networkKey.GetValue("IPAddress");

                    string[] defaultGateways = (string[])networkKey.GetValue("DefaultGateway");

                    string[] subnetmasks = (string[])networkKey.GetValue("SubnetMask");

                    foreach (string ipaddress in ipaddresses)
                    {

                        Console.WriteLine(" IP Address: {0}", ipaddress);

                    }

                    foreach (string subnetmask in subnetmasks)
                    {

                        Console.WriteLine(" Subnet Mask: {0}", subnetmask);

                    }

                    foreach (string defaultGateway in defaultGateways)
                    {

                        Console.WriteLine(" Gateway: {0}", defaultGateway);

                    }

                    networkKey.Close();

                }

            }

            start.Close();


        }

        public bool GetNetWork(string IP, string Mask, ref string start, ref int length)
        {
            string[] Iptmp = IP.Split('.');
            int tIP = 0;
            int iIP = 0;
            int iMask = 0;
            for (int i = 0; i < 4; i++)    // 把IP从字符串的表示形式改成整型的形式
            {
                tIP = byte.Parse(Iptmp[i]);
                iIP += (tIP << (3 - i) * 8);
            }

            Iptmp = Mask.Split('.');
            for (int i = 0; i < 4; i++)    // 把掩码从字符串的表示形式改成整型的形式
            {
                tIP = byte.Parse(Iptmp[i]);
                iMask += (tIP << (3 - i) * 8);
            }

            tIP = iIP & iMask;

            start = ((byte)(tIP >> 24)).ToString();    // 网络ID, IP段
            for (int i = 1; i < 4; i++)
            {
                start += "." + ((byte)(tIP >> (3 - i) * 8)).ToString();
            }
            length = (int)(0xffffffff - iMask);
            //int iend = tIP + z;
            //end = ((byte)(iend >> 24)).ToString();    // 网络ID, IP段
            //for (int i = 1; i < 4; i++)
            //{
            //    end += "." + ((byte)(iend >> (3 - i) * 8)).ToString();
            //}
            return true;
        }


        private void btnLocalFileTest_Click(object sender, EventArgs e)
        {
            System.Threading.Thread localtest = new System.Threading.Thread(new System.Threading.ThreadStart(DumpTestData));
            localtest.Start();
        }

        private void DumpTestData()
        {
            byte[] buffer = new byte[16 * 1024];
            System.IO.FileStream fs = new System.IO.FileStream("test.3gp", System.IO.FileMode.Open);
            //每秒166K数据
            int length_read = 0;
            System.DateTime time_send = System.DateTime.Now;
            System.Console.WriteLine("start play " + time_send.ToString());
            while (true)
            {
                int data_length = fs.Read(buffer, 0, buffer.Length);
                if (length_read == 0)
                {
                    //第一次读
                    this.m_VideoDumpper.PushHeader(buffer, VideoDumpper.HeaderLength);
                }
                length_read += data_length;
                m_VideoDumpper.PushData(buffer, data_length);
                if (data_length != buffer.Length) break;
                //if(((TimeSpan)(System.DateTime.Now - time_send)).;
                System.Threading.Thread.Sleep(90);
            }
            System.Console.WriteLine("end play " + System.DateTime.Now.ToString());
            fs.Close();
        }


        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox1.SelectedItem != null)
            {
                RemoteService obj = listBox1.SelectedItem as RemoteService;
                textBox1.Text = obj.Ip;
            }
        }
    }

    class RemoteService
    {
        public string Ip;
        public int Port;
        public string Name;
        public string ProductVersion;
        
        public class VideoParameters
        {
            public int m_FrameRate;
            public int m_PixWidth;
            public int m_PixHeight;
            public int m_Format;
            public string m_Model;
            public string m_IMEI;
        }

        public string m_paras;
        VideoParameters m_VideoParameters = new VideoParameters();
        public void ParsePara()
        {
            string[] args = m_paras.Split(new char[]{'&'});
            for (int i = 0; i < args.Length; i++)
            {
                string[] pair = args[i].Split(new char[]{'='});
                if (pair[0] == "format") m_VideoParameters.m_Format = int.Parse(pair[1]);
                if (pair[0] == "width") m_VideoParameters.m_PixWidth = int.Parse(pair[1]);
                if (pair[0] == "height") m_VideoParameters.m_PixHeight = int.Parse(pair[1]);
                if (pair[0] == "framerate") m_VideoParameters.m_FrameRate = int.Parse(pair[1]);
                if (pair[0] == "model") m_VideoParameters.m_Model = pair[1];
                if (pair[0] == "imei") m_VideoParameters.m_IMEI = pair[1];
            }
        }
        public override string ToString()
        {
            return "[" + Ip + "]" + m_VideoParameters.m_Model + "(" + m_VideoParameters.m_IMEI + ")" ;
        }
    }
}
